package com.wswy.wzcx.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.che.libcommon.utils.RxHelper;
import com.che.libcommon.utils.ToastUtils;
import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX.Req;
import com.tencent.mm.opensdk.modelmsg.WXImageObject;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.wswy.wzcx.AppContext;
import com.wswy.wzcx.R;
import com.wswy.wzcx.aanewApi.baseUtils.Toast;
import com.wswy.wzcx.aanewApi.baseUtils.Utils;
import com.wswy.wzcx.model.ShareResultResp;
import com.wswy.wzcx.model.home.RPaths;
import com.wswy.wzcx.utils.ShareDialog.OnChooseShareTypeCallback;
import com.wswy.wzcx.widget.dialog.MarketDialog;
import com.wswy.wzcx.widget.dialog.MarketResultDialog;

import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Predicate;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;

/**
 * Created by wangduheng26 on 2017/12/18.
 * wangduheng26@gmail.com
 */

public class ShareHelper {
    public static final String TAG = "ShareHelper";
    public static String WX_APP_ID = "wxeceedc86689c62ad";

    public static String WX_SHARE_HANDLE_RESULT = "key.wx.share.handle.result";
    static String WX_PAY_HANDLE_RESULT = "key.wx.pay.handle.result";
    static String ALI_PAY_HANDLE_RESULT_2 = "key.ali.pay.handle.result";
    static int THUMB_SIZE = 150;
    private static IWXAPI api;


    private static final String share_url = "http://a.app.qq.com/o/simple.jsp?pkgname=com.wswy.wzcx";
    private static final String share_title = "我在用12123查违章APP，推荐给你！";
    private static final String share_desc = "我们提供违章查询、驾考预约、违章代缴、年检代办、0元停车等免费服务服务，诸多服务，一手掌握。";
    private static final String share_icon = "";


    /**
     * 好友
     */
    public static final int TYPE_WX_FRIEND = SendMessageToWX.Req.WXSceneSession;

    /**
     * 朋友圈
     */
    public static final int TYPE_WX_TIMELINE = SendMessageToWX.Req.WXSceneTimeline;

    static {
        try {
            api = WXAPIFactory.createWXAPI(AppContext.getContext(), WX_APP_ID, true);
            api.registerApp(WX_APP_ID);
        } catch (Exception e) {
            Log.e(TAG, "wechat registerApp ex--->", e);
        }
    }


    public static String login() {
        if (!api.isWXAppInstalled()) {
            ToastUtils.showText("未安装微信");
            return null;
        }
        String state = "wzcx_auth_" + System.currentTimeMillis();
        SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
        req.state = state;
        if (api.sendReq(req)) {
            return state;
        }
        return null;
    }

    public static void shareApp(final Context context) {

        new ShareDialog(context, new OnChooseShareTypeCallback() {
            @Override
            public void onChooseType(int shareType) {
                ShareHelper.shareUrl(AppContext.getContext(), shareType, share_url, share_title, share_desc, share_icon);
            }
        }).show();

    }

    public static void gotoMarket(final Context context) {
        MarketDialog.Builder builder = new MarketDialog.Builder(context);
        builder.setPositiveButton((dialog, which) -> {
            RPaths.comment_market = true;
            Utils.gotoMatket(context);
        });
        builder.create().show();
    }

    public static void gotoMarketResult(final Context context) {
        MarketResultDialog.Builder builder = new MarketResultDialog.Builder(context);
        builder.setPositiveButton(() -> {
            Tools.copy(context, "cwzapp12123");
            new Handler().postDelayed((Runnable) () -> {
                AppUtils.launchApp("com.tencent.mm");
            }, 500);
        });
        new Handler().postDelayed((Runnable) () -> {
            builder.create().show();
        }, 500);
    }

    private static SingleObserver<? super SendMessageToWX.Req> generateObserver() {
        return new SingleObserver<SendMessageToWX.Req>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onSuccess(SendMessageToWX.Req req) {
                if (req != null) {
                    api.sendReq(req);
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.e("wdh", ": ", e);
            }

        };

    }

    public static void sharePic(Context context, final String imagePath, final int shareType) {
        Single.fromCallable(new Callable<SendMessageToWX.Req>() {
            @Override
            public SendMessageToWX.Req call() throws Exception {
                WXImageObject imageObject = new WXImageObject();
                imageObject.imagePath = imagePath;

                WXMediaMessage msg = new WXMediaMessage();
                msg.mediaObject = imageObject;

                Bitmap bmp = extractThumbNail(imagePath, THUMB_SIZE, THUMB_SIZE, false);
                msg.thumbData = bmpToByteArray(bmp, true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("image");
                req.message = msg;
                req.scene = shareType;

                return req;
            }
        }).filter(new Predicate<SendMessageToWX.Req>() {
            @Override
            public boolean test(SendMessageToWX.Req req) throws Exception {
                return req != null;
            }
        })
                .toSingle()
                .compose(RxHelper.<Req>io2main())
                .subscribe(generateObserver());
    }

    /**
     * @param type    SendMessageToWX.Req.WXSceneSession or SendMessageToWX.Req.WXSceneTimeline
     * @param url
     * @param title
     * @param des
     * @param iconUrl
     */
    public static void shareUrl(Context context, int type, @NonNull String url, @NonNull String title, @NonNull String des, @Nullable String iconUrl) {
        ShareResultResp resp = new ShareResultResp();
        resp.type = type;
        resp.url = url;
        resp.title = title;
        resp.des = des;
        resp.iconUrl = iconUrl;
        shareUrl(context, resp);
    }

    public static void shareUrl(final Context context, final ShareResultResp resp) {
        Single.fromCallable(new Callable<SendMessageToWX.Req>() {
            @Override
            public SendMessageToWX.Req call() throws Exception {
                int type = resp.type;
                if (type == SendMessageToWX.Req.WXSceneSession || type == SendMessageToWX.Req.WXSceneTimeline) {
                    WXWebpageObject webpage = new WXWebpageObject();
                    webpage.webpageUrl = resp.url;
                    WXMediaMessage msg = new WXMediaMessage(webpage);
                    msg.title = resp.title;
                    msg.description = resp.des;
                    if (TextUtils.isEmpty(resp.iconUrl)) {
                        Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);

                        if (bmp == null) {
                            Drawable drawable = ContextCompat
                                    .getDrawable(context, R.mipmap.ic_launcher);
                            bmp = ImageUtils.drawable2Bitmap(drawable);
                        }

                        Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
                        bmp.recycle();
                        msg.thumbData = bmpToByteArray(thumbBmp, true);
                    } else {
                        msg.thumbData = FrescoUtils.syncWXFetchBitmap(resp.iconUrl, THUMB_SIZE, THUMB_SIZE);
                    }
                    SendMessageToWX.Req req = new SendMessageToWX.Req();
                    req.transaction = buildTransaction("webpage");
                    req.message = msg;
                    req.scene = type;
                    return req;
                }
                return null;
            }
        }).filter(new Predicate<SendMessageToWX.Req>() {
            @Override
            public boolean test(SendMessageToWX.Req req) throws Exception {
                return req != null;
            }
        })
                .toSingle()
                .compose(RxHelper.<Req>io2main())
                .subscribe(generateObserver());


    }

    private static String buildTransaction(final String type) {
        return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
    }

    public static boolean checkInstallWX() {
        return api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
    }

    public static boolean isWXAppInstalled() {
        return api.isWXAppInstalled();
    }

    /**
     * check this phone is support wechat pay
     *
     * @return
     */
    public static boolean checkSupportWXPAY() {
        return false;
    }


    public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
        if (needRecycle) {
            bmp.recycle();
        }

        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static byte[] getHtmlByteArray(final String url) {
        URL htmlUrl = null;
        InputStream inStream = null;
        try {
            htmlUrl = new URL(url);
            URLConnection connection = htmlUrl.openConnection();
            HttpURLConnection httpConnection = (HttpURLConnection) connection;
            int responseCode = httpConnection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                inStream = httpConnection.getInputStream();
                return inputStreamToByte(inStream);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] inputStreamToByte(InputStream is) {
        try {
            ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
            int ch;
            while ((ch = is.read()) != -1) {
                bytestream.write(ch);
            }
            byte imgdata[] = bytestream.toByteArray();
            bytestream.close();
            return imgdata;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static byte[] readFromFile(String fileName, int offset, int len) {
        if (fileName == null) {
            return null;
        }

        File file = new File(fileName);
        if (!file.exists()) {
            Log.i(TAG, "readFromFile: file not found");
            return null;
        }

        if (len == -1) {
            len = (int) file.length();
        }

        Log.d(TAG, "readFromFile : offset = " + offset + " len = " + len + " offset + len = " + (offset + len));

        if (offset < 0) {
            Log.e(TAG, "readFromFile invalid offset:" + offset);
            return null;
        }
        if (len <= 0) {
            Log.e(TAG, "readFromFile invalid len:" + len);
            return null;
        }
        if (offset + len > (int) file.length()) {
            Log.e(TAG, "readFromFile invalid file len:" + file.length());
            return null;
        }

        byte[] b = null;
        RandomAccessFile in = null;
        try {
            in = new RandomAccessFile(fileName, "r");
            b = new byte[len];
            in.seek(offset);
            in.readFully(b);
        } catch (Exception e) {
            Log.e(TAG, "readFromFile : errMsg = " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return b;
    }

    private static final int MAX_DECODE_PICTURE_SIZE = 1920 * 1440;

    public static Bitmap extractThumbNail(final String path, final int height, final int width, final boolean crop) {
        //Assert.assertTrue(path != null && !path.equals("") && height > 0 && width > 0);

        BitmapFactory.Options options = new BitmapFactory.Options();

        try {
            options.inJustDecodeBounds = true;
            Bitmap tmp = BitmapFactory.decodeFile(path, options);
            if (tmp != null) {
                tmp.recycle();
                tmp = null;
            }

            Log.d(TAG, "extractThumbNail: round=" + width + "x" + height + ", crop=" + crop);
            final double beY = options.outHeight * 1.0 / height;
            final double beX = options.outWidth * 1.0 / width;
            Log.d(TAG, "extractThumbNail: extract beX = " + beX + ", beY = " + beY);
            options.inSampleSize = (int) (crop ? (beY > beX ? beX : beY) : (beY < beX ? beX : beY));
            if (options.inSampleSize <= 1) {
                options.inSampleSize = 1;
            }

            // NOTE: out of memory error
            while (options.outHeight * options.outWidth / options.inSampleSize > MAX_DECODE_PICTURE_SIZE) {
                options.inSampleSize++;
            }

            int newHeight = height;
            int newWidth = width;
            if (crop) {
                if (beY > beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            } else {
                if (beY < beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            }

            options.inJustDecodeBounds = false;

            Log.i(TAG, "bitmap required size=" + newWidth + "x" + newHeight + ", orig=" + options.outWidth + "x" + options.outHeight + ", sample=" + options.inSampleSize);
            Bitmap bm = BitmapFactory.decodeFile(path, options);
            if (bm == null) {
                Log.e(TAG, "bitmap decode failed");
                return null;
            }

            Log.i(TAG, "bitmap decoded size=" + bm.getWidth() + "x" + bm.getHeight());
            final Bitmap scale = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
            if (scale != null) {
                bm.recycle();
                bm = scale;
            }

            if (crop) {
                final Bitmap cropped = Bitmap.createBitmap(bm, (bm.getWidth() - width) >> 1, (bm.getHeight() - height) >> 1, width, height);
                if (cropped == null) {
                    return bm;
                }

                bm.recycle();
                bm = cropped;
                Log.i(TAG, "bitmap croped size=" + bm.getWidth() + "x" + bm.getHeight());
            }
            return bm;

        } catch (final OutOfMemoryError e) {
            Log.e(TAG, "decode bitmap failed: " + e.getMessage());
            options = null;
        }

        return null;
    }

    public static boolean supportMiniProgram() {
        try {
            return api.getWXAppSupportAPI() >= Build.LAUNCH_MINIPROGRAM_SUPPORTED_SDK_INT;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void startMiniProgram(String miniProgram, String path) {
        WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
        req.userName = miniProgram; // 填小程序原始id
        if (!TextUtils.isEmpty(path)) {
            req.path = path;                  //拉起小程序页面的可带参路径，不填默认拉起小程序首页
        }
        req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;// 可选打开 开发版，体验版和正式版
        api.sendReq(req);
    }

    public static IWXAPI getWXApi() {
        return api;
    }
}
